import { expect, test } from 'vitest'

import { getDefaultConfig } from '../src'
import { ClassPartObject, createClassMap } from '../src/lib/class-group-utils'

test('class map has correct class groups at first part', () => {
    const classMap = createClassMap(getDefaultConfig())

    const classGroupsByFirstPart = Object.fromEntries(
        Array.from(classMap.nextPart.entries()).map(([key, value]) => [
            key,
            Array.from(getClassGroupsInClassPart(value)).sort(),
        ]),
    )

    expect(classMap.classGroupId).toBeUndefined()
    expect(classMap.validators).toBeNull()
    expect(classGroupsByFirstPart).toEqual({
        absolute: ['position'],
        accent: ['accent'],
        align: ['vertical-align'],
        animate: ['animate'],
        antialiased: ['font-smoothing'],
        appearance: ['appearance'],
        aspect: ['aspect'],
        auto: ['auto-cols', 'auto-rows'],
        backdrop: [
            'backdrop-blur',
            'backdrop-brightness',
            'backdrop-contrast',
            'backdrop-filter',
            'backdrop-grayscale',
            'backdrop-hue-rotate',
            'backdrop-invert',
            'backdrop-opacity',
            'backdrop-saturate',
            'backdrop-sepia',
        ],
        backface: ['backface'],
        basis: ['basis'],
        bg: [
            'bg-attachment',
            'bg-blend',
            'bg-clip',
            'bg-color',
            'bg-image',
            'bg-origin',
            'bg-position',
            'bg-repeat',
            'bg-size',
        ],
        block: ['display'],
        blur: ['blur'],
        border: [
            'border-collapse',
            'border-color',
            'border-color-b',
            'border-color-e',
            'border-color-l',
            'border-color-r',
            'border-color-s',
            'border-color-t',
            'border-color-x',
            'border-color-y',
            'border-spacing',
            'border-spacing-x',
            'border-spacing-y',
            'border-style',
            'border-w',
            'border-w-b',
            'border-w-e',
            'border-w-l',
            'border-w-r',
            'border-w-s',
            'border-w-t',
            'border-w-x',
            'border-w-y',
        ],
        bottom: ['bottom'],
        box: ['box', 'box-decoration'],
        break: ['break', 'break-after', 'break-before', 'break-inside'],
        brightness: ['brightness'],
        capitalize: ['text-transform'],
        caption: ['caption'],
        caret: ['caret-color'],
        clear: ['clear'],
        col: ['col-end', 'col-start', 'col-start-end'],
        collapse: ['visibility'],
        columns: ['columns'],
        container: ['container'],
        content: ['align-content', 'content'],
        contents: ['display'],
        contrast: ['contrast'],
        cursor: ['cursor'],
        decoration: ['text-decoration-color', 'text-decoration-style', 'text-decoration-thickness'],
        delay: ['delay'],
        diagonal: ['fvn-fraction'],
        divide: [
            'divide-color',
            'divide-style',
            'divide-x',
            'divide-x-reverse',
            'divide-y',
            'divide-y-reverse',
        ],
        drop: ['drop-shadow', 'drop-shadow-color'],
        duration: ['duration'],
        ease: ['ease'],
        end: ['end'],
        field: ['field-sizing'],
        fill: ['fill'],
        filter: ['filter'],
        fixed: ['position'],
        flex: ['display', 'flex', 'flex-direction', 'flex-wrap'],
        float: ['float'],
        flow: ['display'],
        font: ['font-family', 'font-stretch', 'font-weight'],
        forced: ['forced-color-adjust'],
        from: ['gradient-from', 'gradient-from-pos'],
        gap: ['gap', 'gap-x', 'gap-y'],
        grayscale: ['grayscale'],
        grid: ['display', 'grid-cols', 'grid-flow', 'grid-rows'],
        grow: ['grow'],
        h: ['h'],
        hidden: ['display'],
        hue: ['hue-rotate'],
        hyphens: ['hyphens'],
        indent: ['indent'],
        inline: ['display'],
        inset: [
            'inset',
            'inset-ring-color',
            'inset-ring-w',
            'inset-shadow',
            'inset-shadow-color',
            'inset-x',
            'inset-y',
        ],
        invert: ['invert'],
        invisible: ['visibility'],
        isolate: ['isolation'],
        isolation: ['isolation'],
        italic: ['font-style'],
        items: ['align-items'],
        justify: ['justify-content', 'justify-items', 'justify-self'],
        leading: ['leading'],
        left: ['left'],
        line: ['line-clamp', 'text-decoration'],
        lining: ['fvn-figure'],
        list: ['display', 'list-image', 'list-style-position', 'list-style-type'],
        lowercase: ['text-transform'],
        m: ['m'],
        mask: [
            'mask-clip',
            'mask-composite',
            'mask-image',
            'mask-image-b-from-color',
            'mask-image-b-from-pos',
            'mask-image-b-to-color',
            'mask-image-b-to-pos',
            'mask-image-conic-from-color',
            'mask-image-conic-from-pos',
            'mask-image-conic-pos',
            'mask-image-conic-to-color',
            'mask-image-conic-to-pos',
            'mask-image-l-from-color',
            'mask-image-l-from-pos',
            'mask-image-l-to-color',
            'mask-image-l-to-pos',
            'mask-image-linear-from-color',
            'mask-image-linear-from-pos',
            'mask-image-linear-pos',
            'mask-image-linear-to-color',
            'mask-image-linear-to-pos',
            'mask-image-r-from-color',
            'mask-image-r-from-pos',
            'mask-image-r-to-color',
            'mask-image-r-to-pos',
            'mask-image-radial',
            'mask-image-radial-from-color',
            'mask-image-radial-from-pos',
            'mask-image-radial-pos',
            'mask-image-radial-shape',
            'mask-image-radial-size',
            'mask-image-radial-to-color',
            'mask-image-radial-to-pos',
            'mask-image-t-from-color',
            'mask-image-t-from-pos',
            'mask-image-t-to-color',
            'mask-image-t-to-pos',
            'mask-image-x-from-color',
            'mask-image-x-from-pos',
            'mask-image-x-to-color',
            'mask-image-x-to-pos',
            'mask-image-y-from-color',
            'mask-image-y-from-pos',
            'mask-image-y-to-color',
            'mask-image-y-to-pos',
            'mask-mode',
            'mask-origin',
            'mask-position',
            'mask-repeat',
            'mask-size',
            'mask-type',
        ],
        max: ['max-h', 'max-w'],
        mb: ['mb'],
        me: ['me'],
        min: ['min-h', 'min-w'],
        mix: ['mix-blend'],
        ml: ['ml'],
        mr: ['mr'],
        ms: ['ms'],
        mt: ['mt'],
        mx: ['mx'],
        my: ['my'],
        no: ['text-decoration'],
        normal: ['fvn-normal', 'text-transform'],
        not: ['font-style', 'sr'],
        object: ['object-fit', 'object-position'],
        oldstyle: ['fvn-figure'],
        opacity: ['opacity'],
        order: ['order'],
        ordinal: ['fvn-ordinal'],
        origin: ['transform-origin'],
        outline: ['outline-color', 'outline-offset', 'outline-style', 'outline-w'],
        overflow: ['overflow', 'overflow-x', 'overflow-y'],
        overline: ['text-decoration'],
        overscroll: ['overscroll', 'overscroll-x', 'overscroll-y'],
        p: ['p'],
        pb: ['pb'],
        pe: ['pe'],
        perspective: ['perspective', 'perspective-origin'],
        pl: ['pl'],
        place: ['place-content', 'place-items', 'place-self'],
        placeholder: ['placeholder-color'],
        pointer: ['pointer-events'],
        pr: ['pr'],
        proportional: ['fvn-spacing'],
        ps: ['ps'],
        pt: ['pt'],
        px: ['px'],
        py: ['py'],
        relative: ['position'],
        resize: ['resize'],
        right: ['right'],
        ring: ['ring-color', 'ring-offset-color', 'ring-offset-w', 'ring-w', 'ring-w-inset'],
        rotate: ['rotate', 'rotate-x', 'rotate-y', 'rotate-z'],
        rounded: [
            'rounded',
            'rounded-b',
            'rounded-bl',
            'rounded-br',
            'rounded-e',
            'rounded-ee',
            'rounded-es',
            'rounded-l',
            'rounded-r',
            'rounded-s',
            'rounded-se',
            'rounded-ss',
            'rounded-t',
            'rounded-tl',
            'rounded-tr',
        ],
        row: ['row-end', 'row-start', 'row-start-end'],
        saturate: ['saturate'],
        scale: ['scale', 'scale-3d', 'scale-x', 'scale-y', 'scale-z'],
        scheme: ['color-scheme'],
        scroll: [
            'scroll-behavior',
            'scroll-m',
            'scroll-mb',
            'scroll-me',
            'scroll-ml',
            'scroll-mr',
            'scroll-ms',
            'scroll-mt',
            'scroll-mx',
            'scroll-my',
            'scroll-p',
            'scroll-pb',
            'scroll-pe',
            'scroll-pl',
            'scroll-pr',
            'scroll-ps',
            'scroll-pt',
            'scroll-px',
            'scroll-py',
        ],
        select: ['select'],
        self: ['align-self'],
        sepia: ['sepia'],
        shadow: ['shadow', 'shadow-color'],
        shrink: ['shrink'],
        size: ['size'],
        skew: ['skew', 'skew-x', 'skew-y'],
        slashed: ['fvn-slashed-zero'],
        snap: ['snap-align', 'snap-stop', 'snap-strictness', 'snap-type'],
        space: ['space-x', 'space-x-reverse', 'space-y', 'space-y-reverse'],
        sr: ['sr'],
        stacked: ['fvn-fraction'],
        start: ['start'],
        static: ['position'],
        sticky: ['position'],
        stroke: ['stroke', 'stroke-w'],
        subpixel: ['font-smoothing'],
        table: ['display', 'table-layout'],
        tabular: ['fvn-spacing'],
        text: [
            'font-size',
            'text-alignment',
            'text-color',
            'text-overflow',
            'text-shadow',
            'text-shadow-color',
            'text-wrap',
        ],
        to: ['gradient-to', 'gradient-to-pos'],
        top: ['top'],
        touch: ['touch', 'touch-pz', 'touch-x', 'touch-y'],
        tracking: ['tracking'],
        transform: ['transform', 'transform-style'],
        transition: ['transition', 'transition-behavior'],
        translate: ['translate', 'translate-none', 'translate-x', 'translate-y', 'translate-z'],
        truncate: ['text-overflow'],
        underline: ['text-decoration', 'underline-offset'],
        uppercase: ['text-transform'],
        via: ['gradient-via', 'gradient-via-pos'],
        visible: ['visibility'],
        w: ['w'],
        whitespace: ['whitespace'],
        will: ['will-change'],
        wrap: ['wrap'],
        z: ['z'],
    })
})

function getClassGroupsInClassPart(classPart: ClassPartObject): Set<string> {
    const { classGroupId, validators, nextPart } = classPart

    const classGroups = new Set<string>()

    if (classGroupId) {
        classGroups.add(classGroupId)
    }

    if (validators) {
        validators.forEach((validator) => classGroups.add(validator.classGroupId))
    }

    nextPart.forEach((nextClassPart) => {
        getClassGroupsInClassPart(nextClassPart).forEach((classGroup) => {
            classGroups.add(classGroup)
        })
    })

    return classGroups
}
